/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#include "pch.h"
#include <journal/app/constants.h>
#include <journal/app/trace_tags.h>
#include <baja/app/debug_console_trace.hpp>

namespace journal { namespace app {

std::shared_ptr<trace_tag_registry> trace_tag_registry::_singleton;

inline void setTag(const b::uint64 tag, bool b)
{
    if (b)
    {
        baja::app::debugConsoleEnableTag(tag);
    }
    else
    {
        baja::app::debugConsoleDisableTag(tag);
    }
}

void trace_tag_registry::initialize()
{
    _singleton = std::make_shared<trace_tag_registry>();

    _singleton->initializeInternal();
    _singleton->registerTag(TRACE_TAG_INPUT,				L"trace tags\\input",		false);
    _singleton->registerTag(TRACE_TAG_INK,					L"trace tags\\ink",			false);
    _singleton->registerTag(TRACE_TAG_MODEL,				L"trace tags\\model",		false);
    _singleton->registerTag(TRACE_TAG_MODEL_CACHE_MGR,		L"trace tags\\model cache manager", false);
    _singleton->registerTag(TRACE_TAG_INK_RENDERER,			L"trace tags\\ink renderer",false);
    _singleton->registerTag(TRACE_TAG_INK_RENDERER_PERF,	L"trace tags\\ink renderer perf",false);
    _singleton->registerTag(TRACE_TAG_INK_DELETE,			L"trace tags\\ink delete",false);
    _singleton->registerTag(TRACE_TAG_PAGE_VIEW,			L"trace tags\\page view",	false);
    _singleton->registerTag(TRACE_TAG_KEYS,					L"trace tags\\keys",		false);
    _singleton->registerTag(TRACE_TAG_THUMBNAILS,			L"trace tags\\thumbnails",		false);
    _singleton->registerTag(TRACE_TAG_UNDO_REDO,			L"trace tags\\undo redo",		false);
    _singleton->registerTag(TRACE_TAG_GENERIC_MODEL,		L"trace tags\\generic model",		false);
    _singleton->registerTag(TRACE_TAG_RECORDED,				L"trace tags\\recorded events",		false);
    _singleton->registerTag(TRACE_TAG_SLOTS,				L"trace tags\\view slots",		false);
    _singleton->registerTag(TRACE_TAG_OTHER,				L"trace tags\\other",		false);
}

void trace_tag_registry::initialLoad()
{
    if (constants::general::traceToFile())
    {
        DEBUG_CONSOLE_SET_FLAG(TRACE_FLAG_FILE_TRACING);
    }
    else
    {
        DEBUG_CONSOLE_CLEAR_FLAG(TRACE_FLAG_FILE_TRACING);
    }

    if (constants::general::traceToOutput())
    {
        DEBUG_CONSOLE_SET_FLAG(TRACE_FLAG_OUTPUT_TRACING);
    }
    else
    {
        DEBUG_CONSOLE_CLEAR_FLAG(TRACE_FLAG_OUTPUT_TRACING);
    }

    setTag(TRACE_TAG_INPUT, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\input")->getValueBuffer())));
    setTag(TRACE_TAG_INK, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\ink")->getValueBuffer())));
    setTag(TRACE_TAG_MODEL, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\model")->getValueBuffer())));
    setTag(TRACE_TAG_MODEL_CACHE_MGR, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\model cache manager")->getValueBuffer())));
    setTag(TRACE_TAG_INK_RENDERER, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\ink renderer")->getValueBuffer())));
    setTag(TRACE_TAG_INK_RENDERER_PERF, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\ink renderer perf")->getValueBuffer())));
    setTag(TRACE_TAG_INK_DELETE, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\ink delete")->getValueBuffer())));
    setTag(TRACE_TAG_PAGE_VIEW, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\page view")->getValueBuffer())));
    setTag(TRACE_TAG_KEYS, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\keys")->getValueBuffer())));
    setTag(TRACE_TAG_THUMBNAILS, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\thumbnails")->getValueBuffer())));
    setTag(TRACE_TAG_UNDO_REDO, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\undo redo")->getValueBuffer())));
    setTag(TRACE_TAG_GENERIC_MODEL, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\generic model")->getValueBuffer())));
    setTag(TRACE_TAG_RECORDED, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\recorded events")->getValueBuffer())));
    setTag(TRACE_TAG_SLOTS, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\view slots")->getValueBuffer())));
    setTag(TRACE_TAG_OTHER, *(static_cast<bool*>(constants::settings()->findSetting(L"trace tags\\other")->getValueBuffer())));
}

void trace_tag_registry::initializeInternal()
{
    std::shared_ptr<trace_tag_registry> t = shared_from_this();
    std::shared_ptr<isettings_service_observer> o = std::dynamic_pointer_cast<isettings_service_observer>(t);

    _settingsObserverCookie = constants::settings()->addObserver(
        std::dynamic_pointer_cast<isettings_service_observer>(shared_from_this()));
}

void trace_tag_registry::registerTag(const b::uint64 tag, const b::wchar* path, bool defaultValue)
{
    trace_tag_data data;
    data.path = path;
    data.tag = tag;
    data.b = defaultValue;

    setTag(tag, defaultValue);
    constants::settings()->registerBool(-1, path, data.b);
    
    _map[data.path] = data;
}

void trace_tag_registry::onBeforeSettingChange(const b::wchar* fullName)
{
}

void trace_tag_registry::onAfterSettingChange(const b::wchar* fullName)
{
    if (std::wstring(fullName).compare(constants::general::name::traceToFile) == 0)
    {
        if (constants::general::traceToFile())
        {
            DEBUG_CONSOLE_SET_FLAG(TRACE_FLAG_FILE_TRACING);
        }
        else
        {
            DEBUG_CONSOLE_CLEAR_FLAG(TRACE_FLAG_FILE_TRACING);
        }
    }
    else if (std::wstring(fullName).compare(constants::general::name::traceToOutput) == 0)
    {
        if (constants::general::traceToOutput())
        {
            DEBUG_CONSOLE_SET_FLAG(TRACE_FLAG_OUTPUT_TRACING);
        }
        else
        {
            DEBUG_CONSOLE_CLEAR_FLAG(TRACE_FLAG_OUTPUT_TRACING);
        }
    }

    auto it = _map.find(fullName);
    if (it == _map.end())
    {
        return;
    }

    // special case
    bool b = *(static_cast<bool*>(constants::settings()->findSetting(fullName)->getValueBuffer()));
    setTag(it->second.tag, b);
}


}} // namespace journal::app
